package com.syh.jn.scm.service.impl.downstream.purchase;


import cn.redscarf.commons.util.bean.ExtBeanUtils;
import cn.redscarf.commons.util.other.ExtAssert;
import cn.redscarf.commons.wrapper.Restrictions;
import cn.redscarf.commons.wrapper.Wrapper;
import com.alibaba.dubbo.config.annotation.Service;
import com.syh.core.ddd.event.annotation.DomainEventHandle;
import com.syh.core.ddd.infrastructure.repository.AggregateRepository;
import com.syh.core.ddd.service.AbstractServiceImpl;
import com.syh.jn.scm.domain.downstream.entity.finance.DownStatementAccountBill;
import com.syh.jn.scm.domain.downstream.entity.logistics.DownLogisticsBill;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseOrder;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseOrderItem;
import com.syh.jn.scm.domain.downstream.entity.purchase.DownPurchaseReturnOrder;
import com.syh.jn.scm.domain.downstream.event.DownLogisticsBillEvent;
import com.syh.jn.scm.domain.downstream.event.DownPurchaseOrderEvent;
import com.syh.jn.scm.domain.downstream.event.DownPurchaseReturnOrderEvent;
import com.syh.jn.scm.domain.downstream.event.DownStatementAccountBillEvent;
import com.syh.jn.scm.domain.downstream.repository.logistics.DownLogisticsBillRepository;
import com.syh.jn.scm.domain.downstream.repository.purchase.DownPurchaseOrderRepository;
import com.syh.jn.scm.domain.driver.entity.logistics.DriverLogisticsBill;
import com.syh.jn.scm.domain.driver.event.DriverLogisticsBillEvent;
import com.syh.jn.scm.dto.downstream.purchase.*;
import com.syh.jn.scm.dto.support.FilesDto;
import com.syh.jn.scm.service.api.downstream.finance.enums.DownStatementAccountBillEnum;
import com.syh.jn.scm.service.api.downstream.logistics.enums.DownLogisticsBillEnums;
import com.syh.jn.scm.service.api.downstream.purchase.DownPurchaseOrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * Date:2018/7/9
 * Author:Clown
 * 下游采购单基础业务;
 */
@Service
@Transactional
public class DownPurchaseOrderServiceImpl extends AbstractServiceImpl<DownPurchaseOrderSto, DownPurchaseOrderMto, DownPurchaseOrderVo, DownPurchaseOrder, Long> implements DownPurchaseOrderService {
  @Autowired
  private DownPurchaseOrderRepository downstreamPurchaseOrderRepository;
  @Autowired
  private DownLogisticsBillRepository downLogisticsBillRepository;

  @Override
  protected AggregateRepository<DownPurchaseOrder, Long> getAggregateRepository() {
    return downstreamPurchaseOrderRepository;
  }

  /**
   * 新增下游采购订单
   *
   * @param sto 采购订单STO
   * @return
   */
  @Override
  public Long save(DownPurchaseOrderSto sto) {
    DownPurchaseOrder order = DownPurchaseOrder.createByDownStream(sto);
    //返回采购单id
    return downstreamPurchaseOrderRepository.add(order);
  }

  /**
   * 修改下游采购订单
   *
   * @param mto 下游采购单MTO
   */
  @Override
  public void update(DownPurchaseOrderMto mto) {
    DownPurchaseOrder order = judgeNull(mto.getId());
    //调用修改order的方法
    order.modify(mto);
    downstreamPurchaseOrderRepository.update(order);
  }

  /**
   * 上传单据图片
   *
   * @param dto
   */
  @Override
  public void upload(FilesDto dto) {
    DownPurchaseOrder order = judgeNull(dto.getId());
    order.upload(dto);
    downstreamPurchaseOrderRepository.upload(order);
  }

  /**
   * 取消下游采购单
   * @param id
   */
  @Override
  public void cancel(Long id) {
    DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(id);
    order.cancel();
    downstreamPurchaseOrderRepository.update(order, false);
    this.publicEvent(DownPurchaseOrderEvent.buildDownPurchaseOrderCancel(new Object[] {order}));
  }

  @Override
  public DonwPurchaseStatisticalAmountVo statisticalAmount(Wrapper we) {
    return downstreamPurchaseOrderRepository.statisticalAmount(we);
  }

  @Override
  public List<DonwPurchaseStatisticalAmountVo> statisticalAmountByMerchant(Wrapper we) {
    return downstreamPurchaseOrderRepository.statisticalAmountByMerchant(we);
  }

  @Override
  public List<DonwPurchaseStatisticalAmountVo> statisticalAmountByGoods(Wrapper we) {
    return downstreamPurchaseOrderRepository.statisticalAmountByGoods(we);
  }

  /**
   * 删除下游采购订单
   *
   * @param id 被选中的采购单id
   */
  @Override
  public void delete(Long id) {
    DownPurchaseOrder order = judgeNull(id);
    order.destroy();
    downstreamPurchaseOrderRepository.remove(order);
    this.publicEvent(DownPurchaseOrderEvent.buildDownPurchaseOrderDestory(new Object[]{order}));
  }

  private DownPurchaseOrderItemVo trans(DownPurchaseOrderItem entity) {
    DownPurchaseOrderItemVo vo = new DownPurchaseOrderItemVo();
    ExtBeanUtils.copyProperties(entity, vo);
    return vo;
  }

  /**
   * 根据商品id拿到明细商品
   *
   * @param goodsId
   * @return
   */
  @Override
  public DownPurchaseOrderItemVo getByGoodsId(Long goodsId, Long id) {
    return this.trans(downstreamPurchaseOrderRepository.getByGoodsId(goodsId, id));
  }

  /**
   * 判空方法
   *
   * @param id
   * @return
   */
  private DownPurchaseOrder judgeNull(Long id) {
    ExtAssert.notNull(id, "id不能为空");
    DownPurchaseOrder entity = downstreamPurchaseOrderRepository.getById(id);
    ExtAssert.notNull(entity, "订单不存在");
    return entity;
  }

  /**
   * 消费者：监听采购退货单创建（记录已生成退货数量）
   * @param returnOrder
   */
  @DomainEventHandle(DownPurchaseReturnOrderEvent.DOWN_PURCHASE_RETURN_ORDER_CREATED)
  protected void handleDownPurchaseReturnOrderCreated(DownPurchaseReturnOrder returnOrder) {
    DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(returnOrder.getSaleOrderId());
    order.createdReturnOrder(returnOrder);
    downstreamPurchaseOrderRepository.updateOrderAndItems(order);
  }

  /**
   * 消费者：监听采购退货单修改（记录已生成退货数量）
   * @param returnOrder
   */
  @DomainEventHandle(DownPurchaseReturnOrderEvent.DOWN_PURCHASE_RETURN_ORDER_UPDATED)
  protected void handleDownPurchaseReturnOrderUpdated(DownPurchaseReturnOrder returnOrder,DownPurchaseReturnOrder oldReturnOrder) {
    DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(returnOrder.getSaleOrderId());
    order.updatedReturnOrder(returnOrder,oldReturnOrder);
    downstreamPurchaseOrderRepository.updateOrderAndItems(order);
  }

  /**
   * 消费者：监听采购退货单取消（记录已生成退货数量）
   * @param returnOrder
   */
  @DomainEventHandle(DownPurchaseReturnOrderEvent.DOWN_PURCHASE_RETURN_ORDER_CANCEL)
  protected void handleDownPurchaseReturnOrderCancel(DownPurchaseReturnOrder returnOrder) {
    DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(returnOrder.getSaleOrderId());
    order.cancelReturnOrder(returnOrder);
    downstreamPurchaseOrderRepository.updateOrderAndItems(order);
  }

  /**
   * 消费者：监听对账单（生成对账单状态和对账单号）
   * @param bill
   */
  @DomainEventHandle(DownStatementAccountBillEvent.DOWN_STATEMENT_BILL_ACCOUNT_CREATED)
  protected void handleDownStatementBillAccountCreated(DownStatementAccountBill bill) {
    bill.getDownStatementAccountBillItems().forEach(item -> {
      if (item.getSourceType() == DownStatementAccountBillEnum.SOURCE_PURCHASE_ORD.getStatus()) {
        DownPurchaseOrder purchaseOrder = downstreamPurchaseOrderRepository.getById(item.getSourceId());
        purchaseOrder.generating(bill.getId());
        downstreamPurchaseOrderRepository.upload(purchaseOrder);
      }
    });
  }

  /**
   * 消费者：监听对账单（修改对账单状态）
   * @param bill
   */
  @DomainEventHandle(DownStatementAccountBillEvent.DOWN_STATEMENT_BILL_ACCOUNT_UPDATA)
  protected void handleDownStatementBillAccountUpdata(DownStatementAccountBill bill) {
    Wrapper wrapper = Wrapper.build();
    wrapper.append(Restrictions.eq("statementId",bill.getId()));
    List<DownPurchaseOrder> downPurchaseOrders = downstreamPurchaseOrderRepository.getList(wrapper);
    downPurchaseOrders.forEach(downPurchaseOrder -> {
      downPurchaseOrder.cancelGenerating();
      downstreamPurchaseOrderRepository.upload(downPurchaseOrder);
    });
    bill.getDownStatementAccountBillItems().forEach(item -> {
      if (item.getSourceType() == DownStatementAccountBillEnum.SOURCE_PURCHASE_ORD.getStatus()) {
        DownPurchaseOrder purchaseOrder = downstreamPurchaseOrderRepository.getById(item.getSourceId());
        purchaseOrder.generating(bill.getId());
        downstreamPurchaseOrderRepository.upload(purchaseOrder);
      }
    });
  }

  /**
   * 消费者：监听对账单（删除对账单状态和对账单号）
   * @param bill
   */
  @DomainEventHandle(DownStatementAccountBillEvent.DOWN_STATEMENT_BILL_ACCOUNT_DESTORY)
  protected void handleDownStatementBillAccountDestory(DownStatementAccountBill bill) {
    bill.getDownStatementAccountBillItems().forEach(item -> {
      if (item.getSourceType() == DownStatementAccountBillEnum.SOURCE_PURCHASE_ORD.getStatus()) {
        DownPurchaseOrder purchaseOrder = downstreamPurchaseOrderRepository.getById(item.getSourceId());
        purchaseOrder.cancelGenerating();
        downstreamPurchaseOrderRepository.upload(purchaseOrder);
      }
    });
  }

    /**
     * 消费者：监听物流单收货（修改收货数量）
     * @param bill
     */
    @DomainEventHandle(DownLogisticsBillEvent.DOWN_LOGISTICS_BILL_COLLECTED)
    protected void handleLogisticsBillCollected(DownLogisticsBill bill) {
        if (DownLogisticsBillEnums.OrderType.PURCHASE.getStatus().equals(bill.getOrderType())) {
            DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(bill.getOrderId());
            order.collect(bill);
            downstreamPurchaseOrderRepository.updateOrderAndItems(order);
        }
    }

    /**
     * 消费者：监听物流单取消收货（修改收货数量）
     * @param bill
     */
    @DomainEventHandle(DownLogisticsBillEvent.DOWN_LOGISTICS_BILL_UN_RECEIVED)
    protected void handleLogisticsBillUnReceived(DownLogisticsBill bill, DownLogisticsBill oldBill) {
        if (DownLogisticsBillEnums.OrderType.PURCHASE.getStatus().equals(bill.getOrderType())) {
            DownPurchaseOrder order = downstreamPurchaseOrderRepository.getById(bill.getOrderId());
            order.cancelCollect(bill);
            downstreamPurchaseOrderRepository.updateOrderAndItems(order);
        }
    }

  /**
   * 消费者：监听物流单收货（修改收货数量）
   * @param bill
   */
  @DomainEventHandle(DriverLogisticsBillEvent.DRIVER_LOGISTICS_BILL_COLLECTED)
  protected void handleDriverLogisticsBillCollected(DriverLogisticsBill bill) {
    this.handleLogisticsBillCollected(downLogisticsBillRepository.getById(bill.getId()));
  }

}
